Skip to main content

在 CSS 中使用变量

· 6 min read

总结 CSS 变量的基本用法和最佳实践

变量声明

:root {
--foo: 10px;
--bar: 1px solid black;
}

上面的代码中,在根元素选择器内声明了两个变量:--foo--bar

它们和普通的 CSS 属性 fontborder 没有任何区别,因此 CSS 变量也称为 CSS 自定义属性。

但是 CSS 自定义属性并不会指代什么,没有默认含义,比如 font 属性指代了字体,但是这里的 --foo--bar 并没有实际意义,它们的唯一作用就是:用来被赋值给其他 CSS 属性

各种值都可以存放在 CSS 变量中:

:root{
--main-color: #4d4e53;
--main-bg: rgb(255, 255, 255);
--logo-border-color: rebeccapurple;

--header-height: 68px;
--content-padding: 10px 20px;

--base-line-height: 1.428571429;
--transition-duration: .35s;
--external-link: "external link";
--margin-top: calc(2vh + 20px);
}

需要注意的是,变量名大小写敏感,--header-color--Header-Color 是两个不同变量。

var() 函数

var() 函数用于读取变量。

:root {
--foo: skyblue;
--bar: orange;
}
a {
color: var(--foo); // 等价于 color: skyblue
text-decoration-color: var(--bar); // 等价于 text-decoration-color: orange
}

var() 函数还可以使用第二个参数,表示变量的默认值。如果该变量不存在就会使用默认值。

color: var(--foo, #7F583F);

第二个参数不处理内部的逗号或空格,都视作参数的一部分。

var(--font-stack, "Roboto", "Helvetica");
var(--pad, 10px 15px 20px);

var() 函数也可以用在变量声明的地方。

:root {
--primary-color: red;
--logo-text: var(--primary-color);
}

var() 函数也可以进行嵌套使用。

.two {
color: var(--my-var, red); /* Red if --my-var is not defined */
}

.three {
background-color: var(--my-var, var(--my-background, pink)); /* pink if --my-var and --my-background are not defined */
}

变量值类型

如果变量值是字符串,那么可以与其他字符串拼接。

--bar: 'hello';
--foo: var(--bar)' world';

如果变量值是数值,不能与 数值单位 直接连用。

.foo {
--gap: 20;
/* 无效 */
margin-top: var(--gap)px;
}

需要搭配 calc函数 使用。

.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px);
}

如果变量值带有单位,就不能写成字符串。

/* 无效 */
.foo {
--foo: '20px';
font-size: var(--foo);
}

/* 有效 */
.foo {
--foo: 20px;
font-size: var(--foo);
}

变量的作用域

同一个 CSS 变量,可以在多个选择器内声明。读取的时候,优先级最高的声明生效。这与 CSS 的"层叠"(cascade)规则是一致的。还需要注意的是 CSS 变量默认具有 继承性,比如我们在根选择器内定义了一个变量,那么内部的所有元素都继承了该 CSS 变量。

看看下面的 例子

<style>
:root {
--font-color: skyblue;
}

.father {
color: var(--font-color);
}

.child1 {
--font-color: red;
/* 需要重新给 color 赋值,覆盖从 .father 继承过来的 color */
color: var(--font-color);
}

.child2 {
/* 这里的 --font-color 是来自 :root 中声明的变量 */
color: var(--font-color);
}
</style>

<div class="father">
<div class="child1">child1</div>
<div class="child2">child2</div>
</div>

另外,需要注意的是,当浏览器遇到无效的 var() 时,会使用属性的继承值或初始值代替。

最佳实践

JavaScript 操作 CSS 变量

可以使用下面的方式来增删、读写 CSS 变量:

// 设置变量
document.body.style.setProperty('--primary', '#7F583F');

// 读取变量
document.body.style.getPropertyValue('--primary').trim(); // '#7F583F'

// 删除变量
document.body.style.removeProperty('--primary');

下面来看一个 例子

<style>
:root {
--primary-background: orange;
--primary-height: 100px;
}

div {
width: 300px;
height: var(--primary-height);
margin: 100px auto;
border: solid;
background: var(--primary-background);
}
</style>

<div>
<button class='change-background-btn'>ChangeBackground</button>
<button class='change-height-btn'>ChangeHeight</button>
</div>

<script>
const btn1 = document.querySelector(".change-background-btn");
const btn2 = document.querySelector(".change-height-btn");

// 点击第一个按钮,修改 --primary-background 变量值
btn1.addEventListener("click", () => {
document.documentElement.style.setProperty("--primary-background", "#7F583F");
});

// 点击第二个按钮,修改 --primary-height 变量值
btn2.addEventListener("click", () => {
document.documentElement.style.setProperty("--primary-height", "200px");
});
</script>

通过这种方式可以很容易的来修改全局的主题色,当然前提是所有的组件使用的都是相关的 CSS 变量。

结合媒体查询

CSS 变量与媒体查询结合,可以使得不同的屏幕宽度有不同的变量值。

body {
--primary: #7F583F;
--secondary: #F7EFD2;
}

a {
color: var(--primary);
text-decoration-color: var(--secondary);
}

@media screen and (min-width: 768px) {
body {
--primary: #F7EFD2;
--secondary: #7F583F;
}
}

Reference